package selectionSort;

import insertionSort.InsertionSort;
import insertionSort.MyInsertionSort;
import insertionSort.ReversedInsertionSort;
import w5_c1_mergesort.MergeSort;
import w5_c1_mergesort.MySortble;
import w6_c1_quicksort.MyQuickSort;
import w6_c1_quicksort.QuickSort;

import javax.naming.PartialResultException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 排序算法的测试以及性能度量
 */
public class SortingHelper {

    public static <E extends Comparable<E>> boolean isSorted(E[] data) {
        for (int i = 0; i < (data.length - 1); i++)
            if (data[i].compareTo(data[i + 1]) > 0)
                return false;
        return true;
    }

    public static <E extends Comparable<E>> void sortTest(E[] data) {
        String [] sortings = new String[10];
        sortings[2] = "selectionSort.SelectionSort";
        sortings[1] = "insertionSort.InsertionSort";
        sortings[0] = "w5_c1_mergesort.MergeSort";
        for(String sortName : sortings) {
            if(sortName.length() > 1) {
                try {
                    Class sortClass  = Class.forName(sortName);
                    //TODO:bug
//                    obj.sort(data);
                    Method[] ma = sortClass.getMethods();
                    long startTime = System.nanoTime();
                    System.out.println(ma[1]);
//                    Object sortInstance = sortClass.getConstructor().newInstance();
//                    sortMethod.invoke(null,data);
                    // TODO:bug here.
                    //想要通过反射机制，调用SelectionSort类的静态方法sort。但是报错：wrong number of arguments.
                    ma[1].invoke(null,data);
                    long endTime = System.nanoTime();
                    double time = (endTime - startTime) / 1e9;
                    if (!SortingHelper.isSorted(data))
                        throw new RuntimeException(sortName + " failed");
//        System.out.println(time + "s");
                    System.out.println(String.format("%s ,n = %d, time = %f s",sortName, data.length,time));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        int n=100,bound=100;
        Integer[] arr = ArrayGenerator.generateRandomArray(n,bound);
        sortTest(arr);
    }
    public static <E extends Comparable<E>> void sortTest(String name, E[] data) {

        long startTime = System.nanoTime();
        if (name.equals( "SelectionSort"))
            SelectionSort.sort(data);
        if(name.equals("SelectionSortR"))
            SelectionSort.sortRecursive(data);
        if(name.equals("InsertionSort"))
            InsertionSort.sort(data);
        if(name.equals("MyInsertionSortR"))
            MyInsertionSort.sortRecursive(data);
        if(name.equals("ReversedInsertionSort"))
            ReversedInsertionSort.sort(data);
        if(name.equals("ReversedSelectionSort"))
            ReversedSelectionSort.sort(data);
        if(name.equals("MergeSort"))
            MergeSort.sort(data);
        if(name.equals("MergeSort2"))
            MergeSort.sort2(data);
        if(name.equals("MergeSortBU"))
            MergeSort.sortBU(data);
        if(name.equals("MergeSortBU2"))
            MergeSort.sortBU2(data);
        if(name.equals("MyQuickSort"))
            MyQuickSort.sort(data);
        if(name.equals("QuickSort"))
            QuickSort.sort(data);
        if(name.equals("QuickSort2ways"))
            QuickSort.sort2ways(data);
        if(name.equals("QuickSort3ways"))
            QuickSort.sort3ways(data);
        long endTime = System.nanoTime();
        double time = (endTime - startTime) / 1e9;
        if (!SortingHelper.isSorted(data))
            throw new RuntimeException(name + " failed");
//        System.out.println(time + "s");
        System.out.println(String.format("%s ,n = %d, time = %f s",name, data.length,time));

    }
}
